home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / game / shoot / ADescentSrc.lha / descent / main / titles.c < prev    next >
C/C++ Source or Header  |  1998-09-26  |  31KB  |  1,149 lines

  1. /*
  2. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  3. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  4. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  5. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  6. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  7. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  8. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  9. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  10. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
  11. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  12. */
  13. /*
  14.  * $Source: /usr/CVS/descent/main/titles.c,v $
  15.  * $Revision: 1.5 $
  16.  * $Author: nobody $
  17.  * $Date: 1998/09/26 15:12:10 $
  18.  * 
  19.  * Routines to display title screens...
  20.  * 
  21.  * $Log: titles.c,v $
  22.  * Revision 1.5  1998/09/26 15:12:10  nobody
  23.  * Added Warp3D support
  24.  *
  25.  * Revision 1.4  1998/04/09 17:19:14  hfrieden
  26.  * ViRGE briefings reworked
  27.  *
  28.  * Revision 1.3  1998/03/22 16:14:47  hfrieden
  29.  * Title stuff edited for ViRGE support
  30.  *
  31.  * Revision 1.2  1998/03/14 13:54:23  hfrieden
  32.  * Preliminary ViRGE support added
  33.  *
  34.  * Revision 1.1.1.1  1998/03/03 15:12:31  nobody
  35.  * reimport after crash from backup
  36.  *
  37.  * Revision 1.2  1998/02/28 00:34:45  tfrieden
  38.  * aga support
  39.  *
  40.  * Revision 1.1.1.1  1998/02/13  20:20:42  hfrieden
  41.  * Initial Import
  42.  */
  43.  
  44. #pragma off (unreferenced)
  45. static char rcsid[] = "$Id: titles.c,v 1.5 1998/09/26 15:12:10 nobody Exp $";
  46. #pragma on (unreferenced)
  47.  
  48. #include <stdlib.h>
  49. #include <stdio.h>
  50. #include <string.h>
  51.  
  52. #include "types.h"
  53. #include "timer.h"
  54. #include "key.h"
  55. #include "gr.h"
  56. #include "palette.h"
  57. #include "iff.h"
  58. #include "pcx.h"
  59. #include "mem.h"
  60. #include "joy.h"
  61. #include "arcade.h"
  62. #include "coindev.h"
  63. #include "mono.h"
  64. #include "gamefont.h"
  65. #include "cfile.h"
  66. #include "mem.h"
  67. #include "error.h"
  68. #include "polyobj.h"
  69. #include "textures.h"
  70. #include "screens.h"
  71. #include "multi.h"
  72. #include "player.h"
  73. #include "digi.h"
  74. #include "compbit.h"
  75. #include "text.h"
  76. #include "kmatrix.h"
  77. #include "piggy.h"
  78. #include "songs.h"
  79. #include "vfx.h"
  80. #include "newmenu.h"
  81. #include "state.h"
  82.  
  83. #ifdef VIRGIN
  84. #include "VirgeTexture.h"
  85. #endif
  86.  
  87. void title_save_game(void);
  88.  
  89. ubyte New_pal[768];
  90. int New_pal_254_bash;
  91.  
  92. char    * Briefing_text;
  93.  
  94. #define MAX_BRIEFING_COLORS 2
  95.  
  96. char Ending_text_filename[13] = "endreg.tex";
  97. char Briefing_text_filename[13] = "briefing.tex";
  98.  
  99. #define SHAREWARE_ENDING_FILENAME   "ending.tex"
  100.  
  101. //  Can be set by -noscreens command line option.  Causes bypassing of all briefing screens.
  102. int Skip_briefing_screens=0;
  103. int Briefing_foreground_colors[MAX_BRIEFING_COLORS], Briefing_background_colors[MAX_BRIEFING_COLORS];
  104. int Current_color = 0;
  105. int Erase_color;
  106.  
  107. int local_key_inkey(void)
  108. {
  109.     int rval;
  110.  
  111.     rval = key_inkey();
  112.  
  113.     if ( rval==KEY_ALTED+KEY_F2 )   {
  114.         title_save_game();
  115.         return 0;
  116.     }
  117.  
  118.     if (rval == KEY_PRINT_SCREEN) {
  119.         save_screen_shot(0);
  120.         return 0;               //say no key pressed
  121.     }
  122.  
  123.     return rval;
  124. }
  125.  
  126. int show_title_screen( char * filename, int allow_keys )    
  127. {
  128.     fix timer;
  129.     int pcx_error;
  130.     grs_bitmap title_bm;
  131.  
  132.     title_bm.bm_data=NULL;
  133.     if ((pcx_error=pcx_read_bitmap( filename, &title_bm, BM_LINEAR, New_pal ))!=PCX_ERROR_NONE) {
  134.         printf( "File '%s', PCX load error: %s (%i)\n  (No big deal, just no title screen.)\n",filename, pcx_errormsg(pcx_error), pcx_error);
  135.         mprintf((0, "File '%s', PCX load error: %s (%i)\n  (No big deal, just no title screen.)\n",filename, pcx_errormsg(pcx_error), pcx_error));
  136.         Int3();
  137.         return 0;
  138.     }
  139.  
  140.     // vfx_set_palette_sub( New_pal );
  141.     gr_palette_clear(); 
  142.     gr_set_current_canvas( NULL );
  143.     #if defined(VIRGIN) && defined(WARP3D)
  144.     gr_palette_fade_in(New_pal, 1, allow_keys);
  145.     #endif
  146.     gr_bitmap( 0, 0, &title_bm );
  147.     gr_update(NULL);
  148.  
  149.     if (gr_palette_fade_in( New_pal, 32, allow_keys ))  
  150.         return 1;
  151.  
  152.     gr_palette_load( New_pal );
  153.     timer   = timer_get_fixed_seconds() + i2f(3);
  154.     while (1)   {
  155.         if ( local_key_inkey() && allow_keys ) break;
  156.         if ( timer_get_fixed_seconds() > timer ) break;
  157.         keyboard_update();
  158.         #if defined(VIRGIN) && defined(WARP3D)
  159.             gr_update(NULL);
  160.         #endif
  161.  
  162.         #ifdef ARCADE
  163.         {
  164.             int coins;
  165.             coins = coindev_count(0);
  166.             if (coins>0)    {
  167.                 Arcade_timer = F1_0 * ARCADE_FIRST_SECONDS;     // Two minutes to play...
  168.                 if (coins>1)
  169.                     Arcade_timer += F1_0 * ARCADE_CONTINUE_SECONDS*(coins-1);       // Two minutes to play...
  170.                 break;
  171.             }
  172.         }
  173.         #endif
  174.     }           
  175.     if (gr_palette_fade_out( New_pal, 32, allow_keys ))
  176.         return 1;
  177.     free(title_bm.bm_data);
  178.     return 0;
  179. }
  180.  
  181. typedef struct {
  182.     char    bs_name[14];                        //  filename, eg merc01.  Assumes .lbm suffix.
  183.     byte    level_num;
  184.     byte    message_num;
  185.     short   text_ulx, text_uly;         //  upper left x,y of text window
  186.     short   text_width, text_height;    //  width and height of text window
  187. } briefing_screen;
  188.  
  189. #define BRIEFING_SECRET_NUM 31          //  This must correspond to the first secret level which must come at the end of the list.
  190. #define BRIEFING_OFFSET_NUM 4           // This must correspond to the first level screen (ie, past the bald guy briefing screens)
  191.  
  192. //#ifdef SHAREWARE
  193. //#define SHAREWARE_ENDGAME_NUM 11          //  Shareware briefing screen name.
  194. //#else
  195. //#define SHAREWARE_ENDGAME_NUM 34          //  Shareware briefing screen name.
  196. //#define REGISTERED_ENDGAME_NUM    35                  //  Registered briefing screen name.
  197. //#define NUM_REGISTERED_ENDGAME_SCREENS    3           //  Number of registered endgame screens
  198. //#endif
  199.  
  200. #define SHAREWARE_ENDING_LEVEL_NUM      0x7f
  201. #define REGISTERED_ENDING_LEVEL_NUM 0x7e
  202.  
  203. briefing_screen Briefing_screens[] = {
  204.     {   "brief01.pcx",   0,  1,  13, 140, 290,  59 },
  205.     {   "brief02.pcx",   0,  2,  27,  34, 257, 177 },
  206.     {   "brief03.pcx",   0,  3,  20,  22, 257, 177 },
  207.     {   "brief02.pcx",   0,  4,  27,  34, 257, 177 },
  208.  
  209.     {   "moon01.pcx",    1,  5,  10,  10, 300, 170 },   // level 1
  210.     {   "moon01.pcx",    2,  6,  10,  10, 300, 170 },   // level 2
  211.     {   "moon01.pcx",    3,  7,  10,  10, 300, 170 },   // level 3
  212.  
  213.     {   "venus01.pcx",   4,  8,  15, 15, 300,  200 },   // level 4
  214.     {   "venus01.pcx",   5,  9,  15, 15, 300,  200 },   // level 5
  215.  
  216.     {   "brief03.pcx",   6, 10,  20,  22, 257, 177 },
  217.     {   "merc01.pcx",    6, 11,  10, 15, 300, 200 },    // level 6
  218.     {   "merc01.pcx",    7, 12,  10, 15, 300, 200 },    // level 7
  219.  
  220. #ifndef SHAREWARE
  221.     {   "brief03.pcx",   8, 13,  20,  22, 257, 177 },
  222.     {   "mars01.pcx",    8, 14,  10, 100, 300,  200 },  // level 8
  223.     {   "mars01.pcx",    9, 15,  10, 100, 300,  200 },  // level 9
  224.     {   "brief03.pcx",  10, 16,  20,  22, 257, 177 },
  225.     {   "mars01.pcx",   10, 17,  10, 100, 300,  200 },  // level 10
  226.  
  227.     {   "jup01.pcx",    11, 18,  10, 40, 300,  200 },   // level 11
  228.     {   "jup01.pcx",    12, 19,  10, 40, 300,  200 },   // level 12
  229.     {   "brief03.pcx",  13, 20,  20,  22, 257, 177 },
  230.     {   "jup01.pcx",    13, 21,  10, 40, 300,  200 },   // level 13
  231.     {   "jup01.pcx",    14, 22,  10, 40, 300,  200 },   // level 14
  232.  
  233.     {   "saturn01.pcx", 15, 23,  10, 40, 300,  200 },   // level 15
  234.     {   "brief03.pcx",  16, 24,  20,  22, 257, 177 },
  235.     {   "saturn01.pcx", 16, 25,  10, 40, 300,  200 },   // level 16
  236.     {   "brief03.pcx",  17, 26,  20,  22, 257, 177 },
  237.     {   "saturn01.pcx", 17, 27,  10, 40, 300,  200 },   // level 17
  238.  
  239.     {   "uranus01.pcx", 18, 28,  100, 100, 300,  200 }, // level 18
  240.     {   "uranus01.pcx", 19, 29,  100, 100, 300,  200 }, // level 19
  241.     {   "uranus01.pcx", 20, 30,  100, 100, 300,  200 }, // level 20
  242.     {   "uranus01.pcx", 21, 31,  100, 100, 300,  200 }, // level 21
  243.  
  244.     {   "neptun01.pcx", 22, 32,  10, 20, 300,  200 },   // level 22
  245.     {   "neptun01.pcx", 23, 33,  10, 20, 300,  200 },   // level 23
  246.     {   "neptun01.pcx", 24, 34,  10, 20, 300,  200 },   // level 24
  247.  
  248.     {   "pluto01.pcx",  25, 35,  10, 20, 300,  200 },   // level 25
  249.     {   "pluto01.pcx",  26, 36,  10, 20, 300,  200 },   // level 26
  250.     {   "pluto01.pcx",  27, 37,  10, 20, 300,  200 },   // level 27
  251.  
  252.     {   "aster01.pcx",  -1, 38,  10, 90, 300,  200 },   // secret level -1
  253.     {   "aster01.pcx",  -2, 39,  10, 90, 300,  200 },   // secret level -2
  254.     {   "aster01.pcx",  -3, 40,  10, 90, 300,  200 },   // secret level -3
  255. #endif
  256.  
  257.     {   "end01.pcx",   SHAREWARE_ENDING_LEVEL_NUM,  1,  23, 40, 320, 200 },     // shareware end
  258. #ifndef SHAREWARE
  259.     {   "end02.pcx",   REGISTERED_ENDING_LEVEL_NUM,  1,  5, 5, 300, 200 },      // registered end
  260.     {   "end01.pcx",   REGISTERED_ENDING_LEVEL_NUM,  2,  23, 40, 320, 200 },        // registered end
  261.     {   "end03.pcx",   REGISTERED_ENDING_LEVEL_NUM,  3,  5, 5, 300, 200 },      // registered end
  262. #endif
  263.  
  264. };
  265.  
  266. #define MAX_BRIEFING_SCREEN (sizeof(Briefing_screens) / sizeof(Briefing_screens[0]))
  267.  
  268.  
  269. char * get_briefing_screen( int level_num )
  270. {
  271.     int i, found_level=0, last_level=0;
  272.  
  273.     for (i = 0; i < MAX_BRIEFING_SCREEN; i++)   {
  274.         if ( found_level && Briefing_screens[i].level_num != level_num )
  275.             return Briefing_screens[last_level].bs_name;
  276.         if (Briefing_screens[i].level_num == level_num )    {
  277.             found_level=1;
  278.             last_level = i;
  279.         }
  280.     }
  281.     return NULL;
  282. }
  283.  
  284.  
  285.  
  286.  
  287. int Briefing_text_x, Briefing_text_y;
  288.  
  289. void init_char_pos(int x, int y)
  290. {
  291.     Briefing_text_x = x;
  292.     Briefing_text_y = y;
  293. }
  294.  
  295. grs_canvas  *Robot_canv = NULL;
  296. vms_angvec  Robot_angles;
  297.  
  298. char    Bitmap_name[32] = "";
  299. #define EXIT_DOOR_MAX   14
  300. #define OTHER_THING_MAX 10      //  Adam: This is the number of frames in your new animating thing.
  301. #define DOOR_DIV_INIT   6
  302. byte    Door_dir=1, Door_div_count=0, Animating_bitmap_type=0;
  303.  
  304. //  -----------------------------------------------------------------------------
  305. void show_bitmap_frame(void)
  306. {
  307.     grs_canvas  *curcanv_save, *bitmap_canv;
  308.     grs_bitmap  *bitmap_ptr;
  309.  
  310.     //  Only plot every nth frame.
  311.     if (Door_div_count) {
  312.         Door_div_count--;
  313.         return;
  314.     }
  315.  
  316.     Door_div_count = DOOR_DIV_INIT;
  317.  
  318.     if (Bitmap_name[0] != 0) {
  319.         char        *pound_signp;
  320.         int     num, dig1, dig2;
  321.  
  322.         //  Set supertransparency color to black
  323.         if (!New_pal_254_bash) {
  324.             New_pal_254_bash = 1;
  325.             New_pal[254*3] = 0;
  326.             New_pal[254*3+1] = 0;
  327.             New_pal[254*3+2] = 0;
  328.             gr_palette_load( New_pal );
  329.             // vfx_set_palette_sub( New_pal );
  330.         }
  331.  
  332.         switch (Animating_bitmap_type) {
  333.             case 0: bitmap_canv = gr_create_sub_canvas(grd_curcanv, 220, 45, 64, 64);   break;
  334.             case 1: bitmap_canv = gr_create_sub_canvas(grd_curcanv, 220, 45, 94, 94);   break;  //  Adam: Change here for your new animating bitmap thing. 94, 94 are bitmap size.
  335.             default:    Int3(); //  Impossible, illegal value for Animating_bitmap_type
  336.         }
  337.  
  338.         curcanv_save = grd_curcanv;
  339.         grd_curcanv = bitmap_canv;
  340.  
  341.         pound_signp = strchr(Bitmap_name, '#');
  342.         Assert(pound_signp != NULL);
  343.  
  344.         dig1 = *(pound_signp+1);
  345.         dig2 = *(pound_signp+2);
  346.         if (dig2 == 0)
  347.             num = dig1-'0';
  348.         else
  349.             num = (dig1-'0')*10 + (dig2-'0');
  350.  
  351.         switch (Animating_bitmap_type) {
  352.             case 0:
  353.                 num += Door_dir;
  354.                 if (num > EXIT_DOOR_MAX) {
  355.                     num = EXIT_DOOR_MAX;
  356.                     Door_dir = -1;
  357.                 } else if (num < 0) {
  358.                     num = 0;
  359.                     Door_dir = 1;
  360.                 }
  361.                 break;
  362.             case 1:
  363.                 num++;
  364.                 if (num > OTHER_THING_MAX)
  365.                     num = 0;
  366.                 break;
  367.         }
  368.  
  369.         Assert(num < 100);
  370.         if (num >= 10) {
  371.             *(pound_signp+1) = (num / 10) + '0';
  372.             *(pound_signp+2) = (num % 10) + '0';
  373.             *(pound_signp+3) = 0;
  374.         } else {
  375.             *(pound_signp+1) = (num % 10) + '0';
  376.             *(pound_signp+2) = 0;
  377.         }
  378.  
  379.         {
  380.             bitmap_index bi;
  381.             bi = piggy_find_bitmap(Bitmap_name);
  382.             bitmap_ptr = &GameBitmaps[bi.index];
  383.             PIGGY_PAGE_IN( bi );
  384.         }
  385.  
  386.         gr_bitmapm(0, 0, bitmap_ptr);
  387.         gr_update(NULL);
  388.  
  389.         grd_curcanv = curcanv_save;
  390.         free(bitmap_canv);
  391.  
  392.         switch (Animating_bitmap_type) {
  393.             case 0:
  394.                 if (num == EXIT_DOOR_MAX) {
  395.                     Door_dir = -1;
  396.                     Door_div_count = 64;
  397.                 } else if (num == 0) {
  398.                     Door_dir = 1;
  399.                     Door_div_count = 64;
  400.                 }
  401.                 break;
  402.             case 1:
  403.                 break;
  404.         }
  405.     }
  406.  
  407. }
  408.  
  409. //  -----------------------------------------------------------------------------
  410. void show_briefing_bitmap(grs_bitmap *bmp)
  411. {
  412.     grs_canvas  *curcanv_save, *bitmap_canv;
  413.  
  414.     bitmap_canv = gr_create_sub_canvas(grd_curcanv, 220, 45, 166, 138);
  415.     curcanv_save = grd_curcanv;
  416.     grd_curcanv = bitmap_canv;
  417.     gr_bitmapm(0, 0, bmp);
  418.     gr_update(NULL);
  419.  
  420.     grd_curcanv = curcanv_save;
  421.     free(bitmap_canv);
  422. }
  423.  
  424. //  -----------------------------------------------------------------------------
  425. void show_spinning_robot_frame(int robot_num)
  426. {
  427.     grs_canvas  *curcanv_save;
  428.  
  429.     if (robot_num != -1) {
  430.         Robot_angles.h += 150;
  431.  
  432.         curcanv_save = grd_curcanv;
  433.         grd_curcanv = Robot_canv;
  434.         Assert(Robot_info[robot_num].model_num != -1);
  435.         draw_model_picture(Robot_info[robot_num].model_num, &Robot_angles);
  436.         #ifdef VIRGIN
  437.         VirgeSwitchBuffer();
  438.         #endif
  439.         #ifdef WARP3D
  440.         WARP_SwitchBuffer();
  441.         #endif
  442.         #ifndef VIRGIN
  443.         gr_update(NULL);
  444.         #endif
  445.         grd_curcanv = curcanv_save;
  446.     }
  447.  
  448. }
  449.  
  450. //  -----------------------------------------------------------------------------
  451. void init_spinning_robot(void)
  452. {
  453.     Robot_angles.p += 0;
  454.     Robot_angles.b += 0;
  455.     Robot_angles.h += 0;
  456.  
  457.     Robot_canv = gr_create_sub_canvas(grd_curcanv, 138, 55, 166, 138);
  458. }
  459.  
  460. //  -----------------------------------------------------------------------------
  461. void init_briefing_bitmap(void)
  462. {
  463.     Robot_canv = gr_create_sub_canvas(grd_curcanv, 138, 55, 166, 138);
  464. }
  465.  
  466. //  -----------------------------------------------------------------------------
  467. //  Returns char width.
  468. //  If show_robot_flag set, then show a frame of the spinning robot.
  469. int show_char_delay(char the_char, int delay, int robot_num, int cursor_flag)
  470. {
  471.     int w, h, aw;
  472.     char    message[2];
  473.     fix start_time;
  474.     int i;
  475.  
  476.     start_time = timer_get_fixed_seconds();
  477.  
  478.     message[0] = the_char;
  479.     message[1] = 0;
  480.  
  481.     gr_get_string_size(message, &w, &h, &aw );
  482.  
  483.     Assert((Current_color >= 0) && (Current_color < MAX_BRIEFING_COLORS));
  484.  
  485.     //  Draw cursor if there is some delay and caller says to draw cursor
  486.     if (cursor_flag && delay) {
  487.         gr_set_fontcolor(Briefing_foreground_colors[Current_color], -1);
  488.         gr_printf(Briefing_text_x+1, Briefing_text_y, "_" );
  489.     }
  490.  
  491.     for (i=0; i<2; i++) {
  492.         if ((robot_num != -1) && (delay != 0))
  493.             show_spinning_robot_frame(robot_num);
  494.         if (delay != 0)
  495.             show_bitmap_frame();
  496.  
  497.         while (timer_get_fixed_seconds() < start_time + delay/2)
  498.             ;
  499.  
  500.         start_time = timer_get_fixed_seconds();
  501.     }
  502.  
  503.     //  Erase cursor
  504.     if (cursor_flag && delay) {
  505.         gr_set_fontcolor(Erase_color, -1);
  506.         gr_printf(Briefing_text_x+1, Briefing_text_y, "_" );
  507.     }
  508.  
  509.     //  Draw the character
  510.     gr_set_fontcolor(Briefing_background_colors[Current_color], -1);
  511.     gr_printf(Briefing_text_x, Briefing_text_y, message );
  512.  
  513.     gr_set_fontcolor(Briefing_foreground_colors[Current_color], -1);
  514.     gr_printf(Briefing_text_x+1, Briefing_text_y, message );
  515.  
  516. //  if (the_char != ' ')
  517. //      if (!digi_is_sound_playing(231))
  518. //          digi_play_sample( 231, F1_0 );
  519.  
  520.     return w;
  521. }
  522.  
  523. //  -----------------------------------------------------------------------------
  524. int load_briefing_screen( int screen_num )
  525. {
  526.     int pcx_error;
  527.  
  528.     if ((pcx_error=pcx_read_bitmap( &Briefing_screens[screen_num].bs_name, &grd_curcanv->cv_bitmap, grd_curcanv->cv_bitmap.bm_type, New_pal ))!=PCX_ERROR_NONE) {
  529.         printf( "File '%s', PCX load error: %s\n  (It's a briefing screen.  Does this cause you pain?)\n",Briefing_screens[screen_num].bs_name, pcx_errormsg(pcx_error));
  530.         printf(0, "File '%s', PCX load error: %s (%i)\n  (It's a briefing screen.  Does this cause you pain?)\n",Briefing_screens[screen_num].bs_name, pcx_errormsg(pcx_error), pcx_error);
  531.         Int3();
  532.         return 0;
  533.     }
  534.  
  535.     return 0;
  536. }
  537.  
  538. #define KEY_DELAY_DEFAULT   ((F1_0*28)/1000)
  539.  
  540. //  -----------------------------------------------------------------------------
  541. int get_message_num(char **message)
  542. {
  543.     int num=0;
  544.  
  545.     while (**message == ' ')
  546.         (*message)++;
  547.  
  548.     while ((**message >= '0') && (**message <= '9')) {
  549.         num = 10*num + **message-'0';
  550.         (*message)++;
  551.     }
  552.  
  553.     while (*(*message)++ != 10)     //  Get and drop eoln
  554.         ;
  555.  
  556.     return num;
  557. }
  558.  
  559. void title_save_game(void)
  560. {
  561.     grs_canvas * save_canv;
  562.     grs_canvas * save_canv_data;
  563.     grs_font * save_font;
  564.     ubyte palette[768];
  565.  
  566. //    if ( Next_level_num == 0 ) return;
  567.     
  568.     save_canv = grd_curcanv;
  569.     save_font = grd_curcanv->cv_font;
  570.  
  571.     save_canv_data = gr_create_canvas( grd_curcanv->cv_bitmap.bm_w, grd_curcanv->cv_bitmap.bm_h );
  572.     gr_set_current_canvas(save_canv_data);
  573.     gr_ubitmap(0,0,&save_canv->cv_bitmap);
  574.  
  575.     gr_update(NULL);
  576.  
  577.  
  578.     gr_set_current_canvas(save_canv);
  579.     gr_clear_canvas(gr_find_closest_color_current( 0, 0, 0));
  580.     gr_palette_read( palette );
  581.     gr_palette_load( gr_palette );
  582.     state_save_all(1);
  583.     gr_palette_clear();
  584.     
  585.     gr_set_current_canvas(save_canv);
  586.     gr_ubitmap(0,0,&save_canv_data->cv_bitmap);
  587.  
  588.     gr_update(NULL);
  589.  
  590.     gr_palette_load( palette );
  591.     gr_set_curfont(save_font);
  592. }
  593.  
  594.  
  595. //  -----------------------------------------------------------------------------
  596. void get_message_name(char **message, char *result)
  597. {
  598.     while (**message == ' ')
  599.         (*message)++;
  600.  
  601.     while ((**message != ' ') && (**message != 10)) {
  602.         if (**message != 13)
  603.             *result++ = **message;
  604.         (*message)++;
  605.     }
  606.  
  607.     if (**message != 10)
  608.         while (*(*message)++ != 10)     //  Get and drop eoln
  609.             ;
  610.  
  611.     *result = 0;
  612. }
  613.  
  614. //  -----------------------------------------------------------------------------
  615. void flash_cursor(int cursor_flag)
  616. {
  617.     if (cursor_flag == 0)
  618.         return;
  619.  
  620.     if ((timer_get_fixed_seconds() % (F1_0/2) ) > (F1_0/4))
  621.         gr_set_fontcolor(Briefing_foreground_colors[Current_color], -1);
  622.     else
  623.         gr_set_fontcolor(Erase_color, -1);
  624.  
  625.     gr_printf(Briefing_text_x+1, Briefing_text_y, "_" );
  626.  
  627. }
  628.  
  629. //  -----------------------------------------------------------------------------
  630. //  Return true if message got aborted by user (pressed ESC), else return false.
  631. int show_briefing_message(int screen_num, char *message)
  632. {
  633.     int prev_ch=-1;
  634.     int ch, done=0;
  635.     briefing_screen *bsp = &Briefing_screens[screen_num];
  636.     int delay_count = KEY_DELAY_DEFAULT;
  637.     int key_check;
  638.     int robot_num=-1;
  639.     int rval=0;
  640.     int tab_stop=0;
  641.     int flashing_cursor=0;
  642.     int new_page=0;
  643.  
  644.     Bitmap_name[0] = 0;
  645.  
  646.     Current_color = 0;
  647.  
  648.     //mprintf((0, "Going to print message [%s] \n", message));
  649.     gr_set_curfont( GAME_FONT );    
  650.  
  651.     init_char_pos(bsp->text_ulx, bsp->text_uly);
  652.  
  653.     while (!done) {
  654.         ch = *message++;
  655.         if (ch == '$') {
  656.             ch = *message++;
  657.             if (ch == 'C') {
  658.                 Current_color = get_message_num(&message)-1;
  659.                 Assert((Current_color >= 0) && (Current_color < MAX_BRIEFING_COLORS));
  660.                 prev_ch = 10;
  661.             } else if (ch == 'F') {     //  toggle flashing cursor
  662.                 flashing_cursor = !flashing_cursor;
  663.                 prev_ch = 10;
  664.                 while (*message++ != 10)
  665.                     ;
  666.             } else if (ch == 'T') {
  667.                 tab_stop = get_message_num(&message);
  668.                 prev_ch = 10;                           //  read to eoln
  669.             } else if (ch == 'R') {
  670.                 if (Robot_canv != NULL)
  671.                     {free(Robot_canv); Robot_canv=NULL;}
  672.  
  673.                 init_spinning_robot();
  674.                 robot_num = get_message_num(&message);
  675.                 prev_ch = 10;                           //  read to eoln
  676.             } else if (ch == 'N') {
  677.                 //--grs_bitmap  *bitmap_ptr;
  678.                 if (Robot_canv != NULL)
  679.                     {free(Robot_canv); Robot_canv=NULL;}
  680.  
  681.                 get_message_name(&message, Bitmap_name);
  682.                 strcat(Bitmap_name, "#0");
  683.                 Animating_bitmap_type = 0;
  684.                 prev_ch = 10;
  685.             } else if (ch == 'O') {
  686.                 if (Robot_canv != NULL)
  687.                     {free(Robot_canv); Robot_canv=NULL;}
  688.  
  689.                 get_message_name(&message, Bitmap_name);
  690.                 strcat(Bitmap_name, "#0");
  691.                 Animating_bitmap_type = 1;
  692.                 prev_ch = 10;
  693.             } else if (ch == 'B') {
  694.                 char            bitmap_name[32];
  695.                 grs_bitmap  guy_bitmap;
  696.                 ubyte           temp_palette[768];
  697.                 int         iff_error;
  698.  
  699.                 if (Robot_canv != NULL)
  700.                     {free(Robot_canv); Robot_canv=NULL;}
  701.  
  702.                 get_message_name(&message, bitmap_name);
  703.                 strcat(bitmap_name, ".bbm");
  704.                 guy_bitmap.bm_data = NULL;
  705.                 iff_error = iff_read_bitmap(bitmap_name, &guy_bitmap, BM_LINEAR, temp_palette);
  706.                 Assert(iff_error == IFF_NO_ERROR);
  707.  
  708.                 show_briefing_bitmap(&guy_bitmap);
  709.                 gr_update(NULL);
  710.                 free(guy_bitmap.bm_data);
  711.                 prev_ch = 10;
  712. //          } else if (ch == 'B') {
  713. //              if (Robot_canv != NULL)
  714. //                  {free(Robot_canv); Robot_canv=NULL;}
  715. //
  716. //              bitmap_num = get_message_num(&message);
  717. //              if (bitmap_num != -1)
  718. //                  show_briefing_bitmap(Textures[bitmap_num]);
  719. //              prev_ch = 10;                           //  read to eoln
  720.             } else if (ch == 'S') {
  721.                 int keypress;
  722.                 fix start_time;
  723.                 fix     time_out_value;
  724.  
  725.                 start_time = timer_get_fixed_seconds();
  726.                 start_time = timer_get_approx_seconds();
  727.                 time_out_value = start_time + i2f(60*5);        // Wait 1 minute...
  728.  
  729.                 while ( (keypress = local_key_inkey()) == 0 ) {     //  Wait for a key
  730.                     if ( timer_get_approx_seconds() > time_out_value ) {
  731.                         keypress = 0;
  732.                         break;                  // Time out after 1 minute..
  733.                     }
  734.                     while (timer_get_fixed_seconds() < start_time + KEY_DELAY_DEFAULT/2)
  735.                         ;
  736.                     flash_cursor(flashing_cursor);
  737.                     show_spinning_robot_frame(robot_num);
  738.                     show_bitmap_frame();
  739.                     start_time += KEY_DELAY_DEFAULT/2;
  740.                 }
  741.  
  742. #ifndef NDEBUG
  743.                 if (keypress == KEY_BACKSP)
  744.                     Int3();
  745. #endif
  746.                 if (keypress == KEY_ESC)
  747.                     rval = 1;
  748.  
  749.                 flashing_cursor = 0;
  750.                 done = 1;
  751.             } else if (ch == 'P') {     //  New page.
  752.                 new_page = 1;
  753.                 while (*message != 10) {
  754.                     message++;  //  drop carriage return after special escape sequence
  755.                 }
  756.                 message++;
  757.                 prev_ch = 10;
  758.             }
  759.         } else if (ch == '\t') {        //  Tab
  760.             if (Briefing_text_x - bsp->text_ulx < tab_stop)
  761.                 Briefing_text_x = bsp->text_ulx + tab_stop;
  762.         } else if ((ch == ';') && (prev_ch == 10)) {
  763.             while (*message++ != 10)
  764.                 ;
  765.             prev_ch = 10;
  766.         } else if (ch == '\\') {
  767.             prev_ch = ch;
  768.         } else if (ch == 10) {
  769.             if (prev_ch != '\\') {
  770.                 prev_ch = ch;
  771.                 Briefing_text_y += 8;
  772.                 Briefing_text_x = bsp->text_ulx;
  773.                 if (Briefing_text_y > bsp->text_uly + bsp->text_height) {
  774.                     load_briefing_screen(screen_num);
  775.                     Briefing_text_x = bsp->text_ulx;
  776.                     Briefing_text_y = bsp->text_uly;
  777.                 }
  778.                 gr_update(NULL);
  779.             } else {
  780.                 if (ch == 13)
  781.                     Int3();
  782.                 prev_ch = ch;
  783.             }
  784.         } else {
  785.             prev_ch = ch;
  786.             Briefing_text_x += show_char_delay(ch, delay_count, robot_num, flashing_cursor);
  787.             if (delay_count != 0) gr_update(NULL);
  788.         }
  789.  
  790.         //  Check for Esc -> abort.
  791.         key_check = local_key_inkey();
  792.         if ( key_check == KEY_ESC ) {
  793.             rval = 1;
  794.             done = 1;
  795.         }
  796.  
  797.         if ( key_check == KEY_ALTED+KEY_F2 )    
  798.             title_save_game();
  799.  
  800.         if ((key_check == KEY_SPACEBAR) || (key_check == KEY_ENTER))
  801.             delay_count = 0;
  802.  
  803.         if (Briefing_text_x > bsp->text_ulx + bsp->text_width) {
  804.             Briefing_text_x = bsp->text_ulx;
  805.             Briefing_text_y += 8;
  806.         }
  807.  
  808.         if ((new_page) || (Briefing_text_y > bsp->text_uly + bsp->text_height)) {
  809.             fix start_time = 0;
  810.             fix time_out_value = 0;
  811.             int keypress;
  812.  
  813.             gr_update(NULL);
  814.             new_page = 0;
  815.             start_time = timer_get_approx_seconds();
  816.             time_out_value = start_time + i2f(60*5);        // Wait 1 minute...
  817.             while ( (keypress = local_key_inkey()) == 0 ) {     //  Wait for a key
  818.                 if ( timer_get_approx_seconds() > time_out_value ) {
  819.                     keypress = 0;
  820.                     break;                  // Time out after 1 minute..
  821.                 }
  822.                 while (timer_get_approx_seconds() < start_time + KEY_DELAY_DEFAULT/2)
  823.                     ;
  824.                 flash_cursor(flashing_cursor);
  825.                 show_spinning_robot_frame(robot_num);
  826.                 show_bitmap_frame();
  827.                 start_time += KEY_DELAY_DEFAULT/2;
  828.             }
  829.  
  830.             robot_num = -1;
  831.  
  832. #ifndef NDEBUG
  833.             if (keypress == KEY_BACKSP)
  834.                 Int3();
  835. #endif
  836.             if (keypress == KEY_ESC) {
  837.                 rval = 1;
  838.                 done = 1;
  839.             }
  840.  
  841.             load_briefing_screen(screen_num);
  842.             Briefing_text_x = bsp->text_ulx;
  843.             Briefing_text_y = bsp->text_uly;
  844.             delay_count = KEY_DELAY_DEFAULT;
  845.             gr_update(NULL);
  846.         }
  847.     }
  848.  
  849.     if (Robot_canv != NULL)
  850.         {free(Robot_canv); Robot_canv=NULL;}
  851.  
  852.     gr_update(NULL);
  853.  
  854.     return rval;
  855. }
  856.  
  857. //  -----------------------------------------------------------------------------
  858. //  Return a pointer to the start of text for screen #screen_num.
  859. char * get_briefing_message(int screen_num)
  860. {
  861.     char    *tptr = Briefing_text;
  862.     int cur_screen=0;
  863.     int ch;
  864.  
  865.     Assert(screen_num >= 0);
  866.  
  867.     while ( (*tptr != 0 ) && (screen_num != cur_screen)) {
  868.         ch = *tptr++;
  869.         if (ch == '$') {
  870.             ch = *tptr++;
  871.             if (ch == 'S')
  872.                 cur_screen = get_message_num(&tptr);
  873.         }
  874.     }
  875.  
  876.     return tptr;
  877. }
  878.  
  879. // -----------------------------------------------------------------------------
  880. //  Load Descent briefing text.
  881. void load_screen_text(char *filename, char **buf)
  882. {
  883.     CFILE   *tfile;
  884.     CFILE *ifile;
  885.     int len, i;
  886.     int have_binary = 0;
  887.  
  888.     if ((tfile = cfopen(filename,"rb")) == NULL) {
  889.         char nfilename[30], *ptr;
  890.  
  891.         strcpy(nfilename, filename);
  892.         ptr = strrchr(nfilename, '.');
  893.         *ptr = '\0';
  894.         strcat(nfilename, ".txb");
  895.         if ((ifile = cfopen(nfilename, "rb")) == NULL)
  896.             Error("Cannot open file %s or %s", filename, nfilename);
  897.         have_binary = 1;
  898.  
  899.         len = cfilelength(ifile);
  900.         //MALLOC(*buf,char, len);//Unable to get this to compile...is it a case issue? -KRB
  901.         *buf=(char *)malloc(len*sizeof(char));//My hack -KRB
  902.         cfread(*buf, 1, len, ifile);
  903.         cfclose(ifile);
  904.     } else {
  905.         len = cfilelength(tfile);
  906.         //MALLOC(*buf, char, len);-KRB
  907.         *buf=(char *)malloc(len*sizeof(char));//-KRB
  908.         cfread(*buf, 1, len, tfile);
  909.         cfclose(tfile);
  910.     }
  911.  
  912.     if (have_binary) {
  913.         char *ptr;
  914.  
  915.         for (i = 0, ptr = *buf; i < len; i++, ptr++) {
  916.             if (*ptr != '\n') {
  917.                 encode_rotate_left(ptr);
  918.                 *ptr = *ptr ^ BITMAP_TBL_XOR;
  919.                 encode_rotate_left(ptr);
  920.             }
  921.         }
  922.     }
  923.  
  924. }
  925.  
  926. //  -----------------------------------------------------------------------------
  927. //  Return true if message got aborted, else return false.
  928. int show_briefing_text(int screen_num)
  929. {
  930.     char    *message_ptr;
  931.  
  932.     // briefing_screen  *bsp = &Briefing_screens[screen_num];
  933.  
  934.     Briefing_foreground_colors[0] = gr_find_closest_color_current( 0, 54, 0);
  935.     Briefing_background_colors[0] = gr_find_closest_color_current( 0, 19, 0);
  936.  
  937.     Briefing_foreground_colors[1] = gr_find_closest_color_current( 42, 38, 32);
  938.     Briefing_background_colors[1] = gr_find_closest_color_current( 14, 14, 14);
  939.  
  940.     Erase_color = gr_find_closest_color_current(0, 0, 0);
  941.  
  942.     message_ptr = get_briefing_message(Briefing_screens[screen_num].message_num);
  943.  
  944.     return show_briefing_message(screen_num, message_ptr);
  945. }
  946.  
  947. //  -----------------------------------------------------------------------------
  948. //  Return true if screen got aborted by user, else return false.
  949. int show_briefing_screen( int screen_num, int allow_keys)
  950. {
  951.     int rval=0;
  952.     int pcx_error;
  953.     grs_bitmap briefing_bm;
  954.  
  955.     New_pal_254_bash = 0;
  956.  
  957.     if (Skip_briefing_screens) {
  958.         mprintf((0, "Skipping briefing screen [%s]\n", &Briefing_screens[screen_num].bs_name));
  959.         return 0;
  960.     }
  961.  
  962.     briefing_bm.bm_data=NULL;   
  963.     if ((pcx_error=pcx_read_bitmap( &Briefing_screens[screen_num].bs_name, &briefing_bm, BM_LINEAR, New_pal ))!=PCX_ERROR_NONE) {
  964.         printf( "PCX load error: %s.  File '%s'\n\n", pcx_errormsg(pcx_error), Briefing_screens[screen_num].bs_name);
  965.         mprintf((0, "File '%s', PCX load error: %s (%i)\n  (It's a briefing screen.  Does this cause you pain?)\n",Briefing_screens[screen_num].bs_name, pcx_errormsg(pcx_error), pcx_error));
  966.         Int3();
  967.         return 0;
  968.     }
  969.  
  970.     // vfx_set_palette_sub( New_pal );
  971.     gr_palette_clear();
  972.     #if defined(VIRGIN) && defined(WARP3D)
  973.     gr_palette_fade_in(New_pal, 1, allow_keys);
  974.     #endif
  975.     gr_bitmap( 0, 0, &briefing_bm );
  976.     gr_update(NULL);
  977.  
  978.     if (gr_palette_fade_in( New_pal, 32, allow_keys ))  
  979.         return 1;
  980.  
  981.     rval = show_briefing_text(screen_num);
  982.     if (gr_palette_fade_out( New_pal, 32, allow_keys ))
  983.         return 1;
  984.     free(briefing_bm.bm_data);
  985.  
  986.     return rval;
  987. }
  988.  
  989.  
  990. //  -----------------------------------------------------------------------------
  991. void do_briefing_screens(int level_num)
  992. {
  993.     int abort_briefing_screens = 0;
  994.     int cur_briefing_screen = 0;
  995.  
  996.     if (Skip_briefing_screens) {
  997.         mprintf((0, "Skipping all briefing screens.\n"));
  998.         return;
  999.     }
  1000.  
  1001.     if (!Briefing_text_filename[0])     //no filename?
  1002.         return;
  1003.  
  1004.     songs_play_song( SONG_BRIEFING, 1 );
  1005.  
  1006.     set_screen_mode( SCREEN_MENU );
  1007.     gr_set_current_canvas(NULL);
  1008.  
  1009.     key_flush();
  1010.  
  1011.     load_screen_text(Briefing_text_filename, &Briefing_text);
  1012.  
  1013.     if (level_num == 1) {
  1014.         while ((!abort_briefing_screens) && (Briefing_screens[cur_briefing_screen].level_num == 0)) {
  1015.             abort_briefing_screens = show_briefing_screen(cur_briefing_screen, 0);
  1016.             cur_briefing_screen++;
  1017.         }
  1018.     }
  1019.  
  1020.     if (!abort_briefing_screens) {
  1021.         for (cur_briefing_screen = 0; cur_briefing_screen < MAX_BRIEFING_SCREEN; cur_briefing_screen++)
  1022.             if (Briefing_screens[cur_briefing_screen].level_num == level_num)
  1023.                 if (show_briefing_screen(cur_briefing_screen, 0))
  1024.                     break;
  1025.     }
  1026.  
  1027.  
  1028.     free(Briefing_text);
  1029.  
  1030.     key_flush();
  1031. }
  1032.  
  1033. #ifndef SHAREWARE
  1034. void do_registered_end_game(void)
  1035. {
  1036.     int cur_briefing_screen;
  1037.  
  1038.     if (!Ending_text_filename[0])       //no filename?
  1039.         return;
  1040.  
  1041.     if ((Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP))
  1042.     {
  1043.         // Special ending for deathmatch!!
  1044.         int len = 40;
  1045.         
  1046.         //MALLOC(Briefing_text, char, len);//Unable to compile -KRB
  1047.         Briefing_text=(char *)malloc(len*sizeof(char));//my hack -KRB
  1048.         sprintf(Briefing_text, "Test");
  1049.     }
  1050.         
  1051.     load_screen_text(Ending_text_filename, &Briefing_text);
  1052.  
  1053.     for (cur_briefing_screen = 0; cur_briefing_screen < MAX_BRIEFING_SCREEN; cur_briefing_screen++)
  1054.         if (Briefing_screens[cur_briefing_screen].level_num == REGISTERED_ENDING_LEVEL_NUM)
  1055.             if (show_briefing_screen(cur_briefing_screen, 0))
  1056.                 break;
  1057.  
  1058. }
  1059. #endif
  1060.  
  1061. void do_shareware_end_game(void)
  1062. {
  1063.     int cur_briefing_screen;
  1064.  
  1065. #ifdef NETWORK
  1066.     if ((Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP))
  1067.     {
  1068. //      // Special ending for deathmatch!!
  1069. //      int len = 120;
  1070. //      int i;
  1071. //      int max_kills = Players[0].net_kills_total;     
  1072. //      int winner = 0;
  1073. //
  1074. //      for (i=1; i < N_players; i++)
  1075. //      {
  1076. //          if (Players[i].net_kills_total > max_kills)
  1077. //          {   
  1078. //              winner = i;
  1079. //              max_kills = Players[i].net_kills_total;
  1080. //          }
  1081. //      }
  1082. //
  1083.         //MALLOC(Briefing_text, char, 4); // Dummy //Can't compile -KRB
  1084.         Briefing_text=(char *)malloc(4*sizeof(char));//my hack -KRB
  1085. //      sprintf(Briefing_text, "$S1\n$C1\n\n%s!\n\n%s has won with %d kills.\n\n$S2\n", TXT_SHAREWARE_DONE,Players[winner].callsign, Players[winner].net_kills_total);
  1086.  
  1087.         kmatrix_view();
  1088.         return;
  1089.     }
  1090.     else 
  1091. #endif
  1092.     {
  1093. #ifdef DEST_SAT
  1094.             load_screen_text(Ending_text_filename, &Briefing_text);
  1095. #else
  1096.             load_screen_text(SHAREWARE_ENDING_FILENAME, &Briefing_text);
  1097. #endif
  1098.     }
  1099.  
  1100.     for (cur_briefing_screen = 0; cur_briefing_screen < MAX_BRIEFING_SCREEN; cur_briefing_screen++)
  1101.         if (Briefing_screens[cur_briefing_screen].level_num == SHAREWARE_ENDING_LEVEL_NUM)
  1102.             if (show_briefing_screen(cur_briefing_screen, 0))
  1103.                 break;
  1104.  
  1105. }
  1106.  
  1107. extern void show_order_form(void);
  1108.  
  1109. void do_end_game(void)
  1110. {
  1111.     set_screen_mode( SCREEN_MENU );
  1112.     gr_set_current_canvas(NULL);
  1113.  
  1114.     key_flush();
  1115.  
  1116.     #ifdef SHAREWARE
  1117.     do_shareware_end_game();        //hurrah! you win!
  1118.     #else
  1119.         #ifdef DEST_SAT
  1120.             do_shareware_end_game();        //hurrah! you win!
  1121.         #else
  1122.             do_registered_end_game();       //hurrah! you win!
  1123.         #endif
  1124.     #endif
  1125.  
  1126.     if (Briefing_text) {
  1127.         free(Briefing_text);
  1128.         Briefing_text = NULL;
  1129.     }
  1130.  
  1131.     key_flush();
  1132.  
  1133.     Function_mode = FMODE_MENU;
  1134.  
  1135.     if ((Game_mode & GM_SERIAL) || (Game_mode & GM_MODEM))
  1136.         Game_mode |= GM_GAME_OVER;
  1137.     else
  1138.         Game_mode = GM_GAME_OVER;
  1139.  
  1140. #ifdef DEST_SAT
  1141.         show_order_form();
  1142. #endif
  1143.  
  1144. #ifdef SHAREWARE
  1145.     show_order_form();
  1146. #endif
  1147. }
  1148.  
  1149.